// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_BASE_GLIB_GLIB_SIGNAL_H_
#define UI_BASE_GLIB_GLIB_SIGNAL_H_

typedef void* gpointer;

// At the time of writing this, there were two common ways of binding our C++
// code to the gobject C system. We either defined a whole bunch of "static
// MethodThunk()" which just called nonstatic Method()s on a class (which hurt
// readability of the headers and signal connection code) OR we declared
// "static Method()" and passed in the current object as the gpointer (and hurt
// readability in the implementation by having "context->" before every
// variable).

// The hopeful result of using these macros is that the code will be more
// readable and regular. There shouldn't be a bunch of static Thunks visible in
// the headers and the implementations shouldn't be filled with "context->"
// de-references.

#define CHROMEG_CALLBACK_0(CLASS, RETURN, METHOD, SENDER)          \
    static RETURN METHOD##Thunk(SENDER sender, gpointer userdata)  \
    {                                                              \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender); \
    }                                                              \
                                                                   \
    RETURN METHOD(SENDER);

#define CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1)         \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one,                \
        gpointer userdata)                                              \
    {                                                                   \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \
    }                                                                   \
                                                                        \
    RETURN METHOD(SENDER, ARG1);

#define CHROMEG_CALLBACK_2(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2)        \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,           \
        gpointer userdata)                                                   \
    {                                                                        \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two); \
    }                                                                        \
                                                                             \
    RETURN METHOD(SENDER, ARG1, ARG2);

#define CHROMEG_CALLBACK_3(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3)         \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                  \
        ARG3 three, gpointer userdata)                                              \
    {                                                                               \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three); \
    }                                                                               \
                                                                                    \
    RETURN METHOD(SENDER, ARG1, ARG2, ARG3);

#define CHROMEG_CALLBACK_4(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3,               \
    ARG4)                                                                                 \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                        \
        ARG3 three, ARG4 four,                                                            \
        gpointer userdata)                                                                \
    {                                                                                     \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four); \
    }                                                                                     \
                                                                                          \
    RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4);

#define CHROMEG_CALLBACK_5(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3,                     \
    ARG4, ARG5)                                                                                 \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                              \
        ARG3 three, ARG4 four, ARG5 five,                                                       \
        gpointer userdata)                                                                      \
    {                                                                                           \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four, five); \
    }                                                                                           \
                                                                                                \
    RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5);

#define CHROMEG_CALLBACK_6(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3,                          \
    ARG4, ARG5, ARG6)                                                                                \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                                   \
        ARG3 three, ARG4 four, ARG5 five,                                                            \
        ARG6 six, gpointer userdata)                                                                 \
    {                                                                                                \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four, five, six); \
    }                                                                                                \
                                                                                                     \
    RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);

#define CHROMEG_VIRTUAL_CALLBACK_0(CLASS, RETURN, METHOD, SENDER)  \
    static RETURN METHOD##Thunk(SENDER sender, gpointer userdata)  \
    {                                                              \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender); \
    }                                                              \
                                                                   \
    virtual RETURN METHOD(SENDER);

#define CHROMEG_VIRTUAL_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1) \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one,                \
        gpointer userdata)                                              \
    {                                                                   \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \
    }                                                                   \
                                                                        \
    virtual RETURN METHOD(SENDER, ARG1);

#define CHROMEG_VIRTUAL_CALLBACK_2(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2) \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,            \
        gpointer userdata)                                                    \
    {                                                                         \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two);  \
    }                                                                         \
                                                                              \
    virtual RETURN METHOD(SENDER, ARG1, ARG2);

#define CHROMEG_VIRTUAL_CALLBACK_3(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2,       \
    ARG3)                                                                           \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                  \
        ARG3 three, gpointer userdata)                                              \
    {                                                                               \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three); \
    }                                                                               \
                                                                                    \
    virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3);

#define CHROMEG_VIRTUAL_CALLBACK_4(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2,             \
    ARG3, ARG4)                                                                           \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                        \
        ARG3 three, ARG4 four,                                                            \
        gpointer userdata)                                                                \
    {                                                                                     \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four); \
    }                                                                                     \
                                                                                          \
    virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4);

#define CHROMEG_VIRTUAL_CALLBACK_5(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2,                   \
    ARG3, ARG4, ARG5)                                                                           \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                              \
        ARG3 three, ARG4 four, ARG5 five,                                                       \
        gpointer userdata)                                                                      \
    {                                                                                           \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four, five); \
    }                                                                                           \
                                                                                                \
    virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5);

#define CHROMEG_VIRTUAL_CALLBACK_6(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2,                        \
    ARG3, ARG4, ARG5, ARG6)                                                                          \
    static RETURN METHOD##Thunk(SENDER sender, ARG1 one, ARG2 two,                                   \
        ARG3 three, ARG4 four, ARG5 five,                                                            \
        ARG6 six, gpointer userdata)                                                                 \
    {                                                                                                \
        return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two, three, four, five, six); \
    }                                                                                                \
                                                                                                     \
    virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);

#endif
